/**
 ****************************************************************************
 * Copyright (C) Marcelo F. Ochoa. All rights reserved.                      *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Apache Software License *
 * version 1.1, a copy of which has been included  with this distribution in *
 * the LICENSE file.                                                         *
 */

package org.apache.cocoon.environment.wrapper;

import java.io.BufferedReader;
import java.io.IOException;
import java.security.Principal;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Vector;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.avalon.framework.parameters.ParameterException;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.acting.DBPrismAction;
import org.apache.cocoon.components.cache.ESIKey;
import org.apache.cocoon.components.cache.Server;

/**
 * Stub implementation for HttpServletRequest class using Cocoon2's request object.
 * - Use src parameter to redefine getServletPath method
 * - Use sitemap parameter Copy-Request-Arguments to merge sitemap parameter
 *   with HttpRequest parameters 
 * - Copy-Request-Arguments, output-attribute and Cache-Control sitemap parameter are not
 *   passed to the stored procedure, they are for internal use.
 * Cocoon2 sitemap entry example:
 * <map:match pattern="content/**.xml">
 *   <map:generate type="db" src="/cms/CMSj.content">
 *     <map:parameter name="Copy-Request-Arguments" value="yes"></map:parameter>
 *     <map:parameter name="Cache-Control" value="External"></map:parameter>
 *     <map:parameter name="source" value="/{1}.xml"></map:parameter>
 *     <map:parameter name="printable" value="no"></map:parameter>
 *   </map:generate>
 *   <map:serialize></map:serialize>
 * </map:match>
 * Copy-Request-Arguments means that HttpRequest arguments will be merged with
 * source and printable
 * Cache-Control external means that DBPrismGenerator will be use an ExternalCache
 * invalidator to control when a DBPrism dynamic page is valid or not.
 * Note: 
 *   Multivalued paramaters are not supported if you are using Copy-Request-Arguments
 *   functionality, then for example html combo box will not work.
 *   Use <map:generate type="db" src="/cms/CMSj.content"></map:generate>
 *   tag alone to solve this
 *   problem, because without sitemap parameter the entire HttpRequest objects is exposed as is.
 */
public class CocoonRequestWrapper implements HttpServletRequest {
    HttpServletRequest request;
    String url;
    public static final String SITEMAPATTRKEY = "org.apache.cocoon.environment.wrapper.SITEMAPATTRKEY";
    boolean useInternalParameter = false;
    Vector names;
    HashMap args;
    Vector attrNames;
    HashMap attrValues;

    public CocoonRequestWrapper(HttpServletRequest request, String src, Parameters par) {
        this.request = request;
        this.url = src;
        this.args = new HashMap();
        this.names = new Vector();
        try {
            //TODO: find a way to get the ConnInfo xform_escape_char parameter value
            if (src.indexOf("^")>0) // pass sitemap parameters as an attribute
                request.setAttribute(SITEMAPATTRKEY,par);
            else {// pass sitemap parameters merged with request parameters
                String namesArgs[] = par.getNames();
                for (int i = 0; i < namesArgs.length; i++) {
                  // If there are one or more parameter into sitemap, switch to this modality
                  useInternalParameter = true;
                  if (Server.CACHE_CONTROL_ARG_NAME.equalsIgnoreCase(namesArgs[i]) ||
                      Server.COPY_ARG_NAME.equalsIgnoreCase(namesArgs[i]) ||
                      DBPrismAction.OUTPUT_ATTRIBUTE.equalsIgnoreCase(namesArgs[i]) ||
                      ESIKey.ESI_ARG_NAME.equalsIgnoreCase(namesArgs[i]))
                          continue; // Skip internal parameter
                  names.add(namesArgs[i]);
                  args.put(namesArgs[i], par.getParameter(namesArgs[i]));
                }
            }
            if (useInternalParameter && Server.COPY_YES.equalsIgnoreCase(par.getParameter(Server.COPY_ARG_NAME, Server.COPY_NO))) {
                Enumeration namesIterator = request.getParameterNames();
                while (namesIterator.hasMoreElements()) {
                    String name = (String)namesIterator.nextElement();
                    String value = request.getParameter(name);
                    names.add(name);
                    args.put(name, value);
                }
            }
        } catch (ParameterException pe) {
            useInternalParameter = false;
        }
    }

    public String getAuthType() { return request.getAuthType(); }

    public Cookie[] getCookies() { return request.getCookies(); }

    public long getDateHeader(String s) { return request.getDateHeader(s); }

    public String getHeader(String s) { return request.getHeader(s); }

    public Enumeration getHeaders(String s) { return request.getHeaders(s); }

    public Enumeration getHeaderNames() { return request.getHeaderNames(); }

    public int getIntHeader(String s) { return request.getIntHeader(s); }

    public String getMethod() { return request.getMethod(); }

    public String getPathInfo() { return request.getPathInfo(); }

    public String getPathTranslated() { return request.getPathTranslated(); }

    public String getContextPath() { return request.getContextPath(); }

    public String getQueryString() { return request.getQueryString(); }

    public String getRemoteUser() { return request.getRemoteUser(); }

    public boolean isUserInRole(String s) { return request.isUserInRole(s); }

    public Principal getUserPrincipal() { return request.getUserPrincipal(); }

    public String getRequestedSessionId() { return request.getRequestedSessionId(); }

    public String getRequestURI() { return request.getRequestURI(); }

    public String getServletPath() { return this.url; }

    public HttpSession getSession(boolean flag) { return request.getSession(flag); }

    public HttpSession getSession() { return request.getSession(); }

    public boolean isRequestedSessionIdValid() { return request.isRequestedSessionIdValid(); }

    public boolean isRequestedSessionIdFromCookie() { return request.isRequestedSessionIdFromCookie(); }

    public boolean isRequestedSessionIdFromURL() { return request.isRequestedSessionIdFromURL(); }

    public boolean isRequestedSessionIdFromUrl() { return request.isRequestedSessionIdFromUrl(); }

    public Object getAttribute(String s) { return request.getAttribute(s); }

    public Enumeration getAttributeNames() { return request.getAttributeNames(); }

    public String getCharacterEncoding() { return request.getCharacterEncoding(); }

    public int getContentLength() { return request.getContentLength(); }

    public String getContentType() { return request.getContentType(); }

    public ServletInputStream getInputStream() throws IOException { return request.getInputStream(); }

    public String getParameter(String s) {
        if (useInternalParameter)
            return (String)args.get(s);
        else
            return request.getParameter(s);
    }

    public Enumeration getParameterNames() {
        if (useInternalParameter)
            return names.elements();
        else
            return request.getParameterNames();
    }

    public String[] getParameterValues(String s) {
        if (useInternalParameter) {
            String[] val = new String[1];
            val[0] = (String)args.get(s);
            return val;
        } else
            return request.getParameterValues(s);
    }

    public String getProtocol() { return request.getProtocol(); }

    public String getScheme() { return request.getScheme(); }

    public String getServerName() { return request.getServerName(); }

    public int getServerPort() { return request.getServerPort(); }

    public BufferedReader getReader() throws IOException { return request.getReader(); }

    public String getRemoteAddr() { return request.getRemoteAddr(); }

    public String getRemoteHost() { return request.getRemoteHost(); }

    public void setAttribute(String s, Object obj) { request.setAttribute(s, obj); }

    public void removeAttribute(String s) { request.removeAttribute(s); }

    public Locale getLocale() { return request.getLocale(); }

    public Enumeration getLocales() { return request.getLocales(); }

    public boolean isSecure() { return request.isSecure(); }

    public RequestDispatcher getRequestDispatcher(String s) { return request.getRequestDispatcher(s); }

    public String getRealPath(String s) { return request.getRealPath(s); }

    public java.lang.StringBuffer getRequestURL() { return null; }

    public java.util.Map getParameterMap() {
        return null;
    }

    public void setCharacterEncoding(java.lang.String $1) { }

  /**
    * @return HttpServletRequest getLocalPort
    */
    public int getLocalPort()
    {
      return this.request.getLocalPort();
    }
    
  /**
    * @return HttpServletRequest getRemotePort
    */
    public int getRemotePort()
    {
      return this.request.getRemotePort();
    }
    
  /**
    * @return HttpServletRequest getLocalAddr
    */
    public String getLocalAddr()
    {
      return this.request.getLocalAddr();
    }
    
  /**
    * @return HttpServletRequest getLocalName
    */
    public String getLocalName()
    {
      return this.request.getLocalName();
    }
    
}
